#ifndef _CONFIGFILE_H
#define _CONFIGFILE_H

#include <cstdlib>
#include <string>
#include <map>
#include <cassert>

using namespace std;

/** '#' is recognized as the head of a comment. And config file only supports English by now */
class ConfigFile {
public:
    static ConfigFile *parseConfig(const char *filePath) throw (string);

    bool put(string key, string value);

    void putByForce(string key, string value) {
        m_config[key] = value;
    }

    bool exist(string key) {
        return getString(key).length() > 0;
    }

    bool change(string key, string value) {
        if (!exist(key)) {
            return false;
        }

        putByForce(key, value);
    }

    string getString(string key) {
        map<string, string>::iterator itr = m_config.find(key);

        if (itr == m_config.end()) {
            assert(false);
        }

        return itr->second;
    }

    bool getBool(string key) throw (string) {
        string value = getString(key);

        if (value == "true") {
            return true;
        } else if (value == "false") {
            return false;
        } else {
            string str("ERROR: the value of key \"");
            str += key + "\" is not bool";

            throw str;
        }
    }

    int getInt(string key) {
        string value = getString(key);

        return atoi(value.c_str());
    }

    float getFloat(string key) {
        string value = getString(key);

        return atof(value.c_str());
    }

    void store(const char *filePath);
    
    ~ConfigFile(void) { }

private:
    map<string, string> m_config;

    ConfigFile(void) { }
};

#endif
